﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;

namespace Vjezbe2
{
    public class TopUpService : ITopUpService
    {
        private ITopUpDataService dataService;
        public TopUpService(ITopUpDataService dataService)
        {
            this.dataService = dataService;
        }
        public void TopUp(TopUpRequest request)
        {
            // defenzivno programiranje
		    if (request == null) throw new ArgumentNullException("request");

		    // logging
		    Debug.WriteLine("TopUp start: {0}, request.AccountId: {1}, request.Amount: {2}", DateTime.Now, request.AccountId, request.Amount);

		    try
		    {
                // transakcija
			    using(var scope = new TransactionScope())
			    {
                    // retry logika
				    var retries = 3;
				    var succeeded = false;
				    while(!succeeded)
				    {
					    try {
                            // poslovna logika
						    int amount = request.Amount;

						    if (amount <= 50)
						    {
							    amount += 10;
						    }
						    else
						    {
							    amount += 20;
						    }

						    dataService.AddAmount(request.AccountId, amount);

						    // commit transakcije
						    scope.Complete();
						    succeeded = true;

						    // logging
						    Console.WriteLine("TopUp end: {0}", DateTime.Now);
					    }
					    catch
					    {
						    // ne bacaj iznimku dok se ne dosegne max retry count
                            if (retries > 1)
                            {
                                retries--;
                                Debug.WriteLine("retrying due to exception: retries={0}", retries);
                            }
                            else
                                throw; 
					    }
				    }
			    }
            }
            catch(Exception ex)
			{
				if (!ExceptionHandler.Handle(ex))
					throw ex;
			}
        }
    }
}
